#include "InputSequences.h"

#include <iostream>

/*
InputSequences::InputSequences() :
		sequences()
{
}
*/

InputSequences::InputSequences(ifstream *_in) :
		sequences(),
		in(_in),
		firstSeq(true),
		bytesRead(0),
		buffPos(0),
		nextName("")
{
}

InputSequences::~InputSequences()
{
}

void InputSequences::addOneSequence()
{
	bool	nameRead = true;
	char seqBuffer[BUFFER_SIZE];
	uint seqBufPos = 0;
	bool readOneSeq = false;
	
	sequences.push_back(InputSequence());
	sequences[sequences.size()-1].setName(nextName);
	while (1)
	{
		while (buffPos < bytesRead)
		{
			if (buffer[buffPos] == '>')
			{
				nameRead = false;
				nextName = "";
			}
			else
			{
				/* Just read the sequence name until the first new-line */
				if (!nameRead)
				{
					if (buffer[buffPos] == '\n')
					{
						nameRead = true;
						if (firstSeq)
						{
							sequences[sequences.size()-1].setName(nextName);
							firstSeq = false;
						}
						else
						{
							readOneSeq = true;
							break;
						}
					}
					else
					{
						nextName = nextName + buffer[buffPos];
					}
				}
				else
				{
					if (buffer[buffPos] != '\n')
					{
						seqBuffer[seqBufPos++] = buffer[buffPos];
						if (seqBufPos % BUFFER_SIZE == 0)
						{
							sequences[sequences.size()-1].append(seqBuffer, BUFFER_SIZE);
							seqBufPos = 0;
						}
					}
				}
			}
			buffPos++;
		}
		if (!readOneSeq && !in->eof())
		{
			in->read(&buffer[0], BUFFER_SIZE);
			bytesRead = in->gcount();
			buffPos = 0;
		}
		else
			break;
	}
	
	/* finished reading, add the last info the the current sequence */
	if (seqBufPos != 0)
		sequences[sequences.size()-1].append(seqBuffer, seqBufPos);
}

void InputSequences::addSequences()
{
	bool first = true;
	bool nameRead = false;
	uint seqBufPos = 0;
	char seqBuffer[BUFFER_SIZE];
	string curName = "";
	uint curSeq = 0;
	//sequences.reserve(10);
	sequences.push_back(InputSequence());

	while (!in->eof())
	{
		in->read(&buffer[0], BUFFER_SIZE);
		streamsize bytesRead = in->gcount();
		for (int i = 0; i < bytesRead; i++)
		{
			if (buffer[i] == '>')
			{
				if (!first)
				{
					/* Starting a new input sequence */
					nameRead = false;
					sequences[curSeq].append(seqBuffer, seqBufPos);
					seqBufPos = 0;
					curSeq++;
					sequences.push_back(InputSequence());
				}
				else
					first = false;
//				sequences[curSeq] = InputSequence();
			}
			else
			{
				/* Just read the sequence name until the first new-line */
				if (!nameRead)
				{
					if (buffer[i] == '\n')
					{
						nameRead = true;
						sequences[curSeq].setName(curName);
						curName = "";
					}
					else
					{
						curName = curName + buffer[i];
					}
				}
				else
				{
					if (buffer[i] != '\n')
					{
						seqBuffer[seqBufPos++] = buffer[i];
						if (seqBufPos % BUFFER_SIZE == 0)
						{
							sequences[curSeq].append(seqBuffer, BUFFER_SIZE);
							seqBufPos = 0;
						}
					}
				}
			}
		}


	}
	/* finished reading, add the last info the the current sequence */
	if (seqBufPos != 0)
		sequences[curSeq].append(seqBuffer, seqBufPos);

}

InputSequence InputSequences::getLastSequence() const
{
	return sequences[sequences.size()-1];
}

InputSequence InputSequences::getSequence(int index) const
{
	return sequences[index];
}

uint InputSequences::getSequencesNum() const
{
	return sequences.size();
}

#ifdef DEBUG

void InputSequences::print() const
{
	for (vector<InputSequence>::const_iterator it = sequences.begin(); it < sequences.end(); it++)
	{
		it->print();
	}
}

#endif /* DEBUG */
